//******************************************************************************
/**
 *
 * @file	fldeff_pokeballon.c
 * @brief	ポケモン吹き出し
 * @author	saito
 * @data	07.06.11
 *
 */
//******************************************************************************
#include "common.h"
#include "fieldsys.h"
#include "field_effect.h"
#include "fieldobj.h"
#include "fldeff_pokeballon.h"

#include "..\system/snd_tool.h"

//==============================================================================
//	define
//==============================================================================
#define P_BALLON_FLDOBJ_Y_OFFSET ((FX32_ONE*32))			///<フィールドOBJからのYオフセット
#define P_BALLON_FLDOBJ_Z_OFFSET ((FX32_ONE*1))				///<フィールドOBJからのZオフセット
#define P_BALLON_FLDOBJ_Y_MOVE_START ((FX32_ONE*6))			///<初速

#define P_BALLON_END_FRAME (2/*30*/)								///<終了フレーム

#define POKE_BALLON_PLTT_SIZE	(16*2)		///16色パレット1本分

#ifdef PM_DEBUG
	int debug_ballon_type = 0;
#endif

//==============================================================================
//	typedef struct
//==============================================================================
//--------------------------------------------------------------
///	FE_P_BALLON型
//--------------------------------------------------------------
typedef struct _TAG_FE_P_BALLON * FE_P_BALLON_PTR;

//--------------------------------------------------------------
///	FE_P_BALLON構造体
//--------------------------------------------------------------
typedef struct _TAG_FE_P_BALLON
{
	FE_SYS *fes;
	BOOL AddFlg;
}FE_P_BALLON;

#define FE_P_BALLON_SIZE (sizeof(FE_P_BALLON)) ///<FE_P_BALLONサイズ

//--------------------------------------------------------------
///	P_BALLON_ADD_H構造体
//--------------------------------------------------------------
typedef struct
{
	FE_SYS *fes;								///<FE_SYS_PTR
	FE_P_BALLON_PTR ballon;						///<FE_P_BALLON
	FIELD_OBJ_PTR fldobj;						///<対象FIELD_OBJ_PTR
}P_BALLON_ADD_H;

#define P_BALLON_ADD_H_SIZE (sizeof(P_BALLON_ADD_H)) ///<P_BALLON_ADD_Hサイズ

typedef struct
{
	TEXANM_DATATBL AnmTbl;						///<アニメテーブル
	NNSG3dResTex* ResTex;						///<パターンを格納したテクスチャのテクスチャリソース
	void *AnmData;								///<アニメテーブルデータ
	void *TexData;								///<テクスチャデータ
	void *TexDstAdr;							///<テクスチャ転送先アドレス
	int TexSize;								///<転送テクスチャサイズ
	u16 Frame;									///<現在のアニメテーブルのフレーム
	u16 TblIdx;									///<アニメテーブルインデックス
}BALLON_ANIME;

//--------------------------------------------------------------
///	P_BALLON_WORK構造体
//--------------------------------------------------------------
typedef struct
{
	int seq_no;									///<動作番号
	int frame;									///<フレーム
	int obj_id;									///<ぎょえー対象OBJID
	int zone_id;								///<ぎょえー対象ゾーンID
	int vanish_sw;								///<非表示SW
	int end_sw;									///<終了SW
	VecFx32 offset;								///<オフセット
	VecFx32 move;								///<移動量
	P_BALLON_ADD_H head;						///<追加時のP_BALLON_ADD_H
	BLACT_WORK_PTR act;							///<ビルボードアクター
	BALLON_ANIME	TexAnime;					///<ＶＲＡＭ転送テクスチャアニメ
}P_BALLON_WORK;

typedef struct BALLON_ARC_DATA_tag
{
	int TexArc;
	int ItpArc;
}BALLON_ARC_DATA;

typedef struct EVENT_BALLON_WORK_tag
{
	int Ballon;
	FIELD_OBJ_PTR FldObj;
}EVENT_BALLON_WORK;

#define P_BALLON_WORK_SIZE (sizeof(P_BALLON_WORK))	///<P_BALLON_WORKサイズ

//==============================================================================
//	プロトタイプ
//==============================================================================
static BOOL PokeBallonEvent(GMEVENT_CONTROL * event);
static void GraphicInit( FE_P_BALLON_PTR ballon );
static void GraphicDelete( FE_P_BALLON_PTR ballon );
static BLACT_WORK_PTR BlActAdd( FE_SYS *fes, VecFx32 *vec );

static BOOL VRAMTransMain(BALLON_ANIME *inAnm);

static const EOA_H_NPP DATA_EoaH_PokeBallon;
const BLACT_ANIME_TBL DATA_BlActAnmTbl_PokeBallon[];



//固定ﾃﾞｰﾀ
static const BALLON_ARC_DATA BallonArcData[BALLON_MAX] = {
	{NARC_fldeff_fuki_heart_nsbtx, NARC_fldeff_fuki_heart_itpcv_dat},
	{NARC_fldeff_fuki_kao01_nsbtx, NARC_fldeff_fuki_kao01_itpcv_dat},
	{NARC_fldeff_fuki_kao02_nsbtx, NARC_fldeff_fuki_kao02_itpcv_dat},
	{NARC_fldeff_fuki_kao03_nsbtx, NARC_fldeff_fuki_kao03_itpcv_dat},
	{NARC_fldeff_fuki_kao04_nsbtx, NARC_fldeff_fuki_kao04_itpcv_dat},
	{NARC_fldeff_fuki_kao05_nsbtx, NARC_fldeff_fuki_kao05_itpcv_dat},
	{NARC_fldeff_fuki_onpu_nsbtx, NARC_fldeff_fuki_onpu_itpcv_dat},
	{NARC_fldeff_fuki_hatena_nsbtx, NARC_fldeff_fuki_hatena_itpcv_dat},
	{NARC_fldeff_fuki_bikkuri_nsbtx, NARC_fldeff_fuki_bikkuri_itpcv_dat},
	{NARC_fldeff_fuki_ase_nsbtx, NARC_fldeff_fuki_ase_itpcv_dat},
	{NARC_fldeff_fuki_komari_nsbtx, NARC_fldeff_fuki_komari_itpcv_dat},
	{NARC_fldeff_fuki_doku_nsbtx, NARC_fldeff_fuki_doku_itpcv_dat},
	{NARC_fldeff_fuki_chinmoku_nsbtx, NARC_fldeff_fuki_chinmoku_itpcv_dat},
	{NARC_fldeff_fuki_pikon_nsbtx, NARC_fldeff_fuki_pikon_itpcv_dat},
};

//==============================================================================
//	ポケモン吹き出し　システム
//==============================================================================
//--------------------------------------------------------------
/**
 * 初期化
 * @param	fes		FE_SYS_PTR
 * @retval	FE_P_BALLON	FE_P_BALLON
 */
//--------------------------------------------------------------
void * FE_PokeBallon_Init( FE_SYS *fes )
{
	FE_P_BALLON_PTR ballon;

	ballon = FE_AllocClearMemory( fes, FE_P_BALLON_SIZE, ALLOC_FR, 0 );
	ballon->fes = fes;
	ballon->AddFlg = FALSE;

	GraphicInit( ballon );	//グラフィック初期化

	return( ballon );
}

//--------------------------------------------------------------
/**
 * 削除
 * @param	ballon		FE_P_BALLON
 * @retval	nothing
 */
//--------------------------------------------------------------
void FE_PokeBallon_Delete( void *work )
{
	FE_P_BALLON_PTR ballon = work;
	GraphicDelete( ballon );
	FE_FreeMemory( ballon );
}

//--------------------------------------------------------------
/**
 * 終了チェック
 * @param	eoa		EOA
 * @retval	int		TRUE=終了
 */
//--------------------------------------------------------------
int FE_PokeBallon_EndCheck( EOA_PTR eoa )
{
	P_BALLON_WORK *work;

	work = EOA_LocalWorkGet( eoa );
	return( work->end_sw );
}

//--------------------------------------------------------------
/**
 * ポケモン吹き出し追加
 * @param	fldobj		FIELD_OBJ_PTR
 * @param	ballon		吹き出しタイプ
 * @retval	EOA_PTR		追加EOA_PTR
 */
//--------------------------------------------------------------
EOA_PTR FE_PokeBallon_Add( FIELD_OBJ_PTR fldobj, int ballon )
{
	int pri;
	P_BALLON_ADD_H head;
	FE_SYS *fes;
	VecFx32 mtx;
	EOA_PTR eoa;


	fes = FE_FieldOBJ_FE_SYS_Get( fldobj );

	head.fes = fes;
	head.ballon = FE_EffectWorkGet( fes, FE_FLD_P_BALLON );
	head.fldobj = fldobj;

	//重複登録はスルーする
	if (head.ballon->AddFlg){
		return NULL;
	}

	head.ballon->AddFlg = TRUE;

	FieldOBJ_VecPosGet( fldobj, &mtx );
	//金銀で追加　描画オフセットも加味する
	{
		VecFx32 ofs_vec;
		FieldOBJ_VecDrawOffsGet( fldobj, &ofs_vec );	//現在オフセット取得
		//Yオフセットは無視
		ofs_vec.y = 0;
		VEC_Add(&mtx, &ofs_vec, &mtx);
	}
	pri = FieldOBJ_TCBStandardPriorityGet( fldobj ) + 1;	//フィールドOBJよりも処理を後に
	eoa = FE_EoaAddNpp( fes, &DATA_EoaH_PokeBallon, &mtx, ballon, &head, pri );

	return( eoa );
}

//--------------------------------------------------------------
/**
 * イベントコール
 * @param	ballon	FE_P_BALLON
 * @retval	nothing
 */
//--------------------------------------------------------------
void PokeBallon_CallEvent(FIELDSYS_WORK *fsys, FIELD_OBJ_PTR fldobj, const int inBallon)
{
	EVENT_BALLON_WORK *wk = sys_AllocMemoryLo(HEAPID_FIELD, sizeof(EVENT_BALLON_WORK));
	wk->Ballon = inBallon;
	wk->FldObj = fldobj;
	//イベントコール
	FieldEvent_Call(fsys->event, PokeBallonEvent, wk);
}

//------------------------------------------------------------------
/**
 * @brief   イベント
 *
 * @param   event		イベントポインタ
 *
 * @retval  BOOL		TRUE:イベント終了　 FALSE;イベント継続
 */
//------------------------------------------------------------------
static BOOL PokeBallonEvent(GMEVENT_CONTROL * event)
{
	int *seq = FieldEvent_GetSeqWork(event);
	EVENT_BALLON_WORK * wk = FieldEvent_GetSpecialWork(event);
	switch(*seq){
	case 0:
#if 0
		//つれポケ以外ポーズ
		{
			FIELDSYS_WORK * fsys = FE_FieldSysWorkGet( FE_FieldOBJ_FE_SYS_Get( wk->FldObj ) );
			FieldOBJSys_MovePauseAll( fsys->fldobjsys );
			FieldOBJ_MovePauseClear( PairPoke_GetFldObjPtr(fsys) );
		}
#endif
		//吹き出し追加
		FE_PokeBallon_Add( wk->FldObj, wk->Ballon );
		(*seq)++;
		break;
	case 1:
		{
			FE_P_BALLON_PTR ballon;
			FE_SYS *fes;
			fes = FE_FieldOBJ_FE_SYS_Get( wk->FldObj );
			ballon = FE_EffectWorkGet( fes, FE_FLD_P_BALLON );
			//吹き出し終了監視
			if (ballon->AddFlg == FALSE){
#if 0
				//ポーズクリア
				{
					FIELDSYS_WORK *fsys = FE_FieldSysWorkGet( fes );
					FieldOBJSys_MovePauseAllClear(fsys->fldobjsys);
				}
#endif
				//メモリ解放
				sys_FreeMemoryEz(wk);
				return TRUE;
			}
		}
		break;
	}

	return FALSE;
}


//--------------------------------------------------------------
/**
 * グラフィック初期化
 * @param	ballon	FE_P_BALLON
 * @retval	nothing
 */
//--------------------------------------------------------------
static void GraphicInit( FE_P_BALLON_PTR ballon )
{
	FE_BlActResAdd_MdlArc( ballon->fes, FE_RESID_MDL_P_BALLON, NARC_fldeff_p_ballon_org_nsbmd );
	FE_BlActResAdd_AnmArc( ballon->fes, FE_RESID_ANM_P_BALLON, NARC_fldeff_kusaeff_itpcv_dat );
	//↑ＤＡＴファイルによるパターンアニメはさせないので、ダミーになれば何でもいい
	FE_BlActResAdd_TexArc( ballon->fes,
		FE_RESID_TEX_P_BALLON, NARC_fldeff_p_ballon_org_nsbtx, TEXRESM_TEX_CUT_TRUE );

	FE_BlActHeaderManageAddResmID( ballon->fes, FE_BLACT_H_ID_P_BALLON,
		FE_RESID_MDL_P_BALLON, FE_RESID_ANM_P_BALLON,
		FE_RESID_TEX_P_BALLON, FE_BLACT_TEX_VRAM,
		DATA_BlActAnmTbl_PokeBallon );
}

//--------------------------------------------------------------
/**
 * グラフィック削除
 * @param	ballon	FE_P_BALLON
 * @retval	nothing
 */
//--------------------------------------------------------------
static void GraphicDelete( FE_P_BALLON_PTR ballon )
{
	FE_BlActResDelete_Mdl( ballon->fes, FE_RESID_MDL_P_BALLON );
	FE_BlActResDelete_Anm( ballon->fes, FE_RESID_ANM_P_BALLON );
	FE_BlActResDelete_Tex( ballon->fes, FE_RESID_TEX_P_BALLON );
	FE_BlActHeaderManageFree( ballon->fes, FE_BLACT_H_ID_P_BALLON );
}

//--------------------------------------------------------------
/**
 * ビルボード追加
 * @param	fes			FE_SYS_PTR
 * @param	vec			座標
 * @retval	BLACT_WORK_PTR	BLACT_WORK_PTR
 */
//--------------------------------------------------------------
static BLACT_WORK_PTR BlActAdd( FE_SYS *fes, VecFx32 *vec )
{
	BLACT_WORK_PTR act = FE_BlActAddID( fes, FE_BLACT_H_ID_P_BALLON, vec );
	NNS_G3dMdlSetMdlFogEnableFlagAll( BLACT_MdlResGet(act), FALSE );	//フォグオフ
	return( act );
}

//--------------------------------------------------------------
/**
 * EOA 　初期化
 * @param	eoa		EOA_PTR
 * @param	wk		eoa work *
 * @retval	int		TRUE=正常終了。FALSE=異常終了
 */
//--------------------------------------------------------------
static int EoaP_Ballon_Init( EOA_PTR eoa, void *wk )
{
	VecFx32 vec;
	P_BALLON_WORK *work;
	const P_BALLON_ADD_H *head;

	work = wk;
	head = EOA_AddPtrGet( eoa );

	work->head = *head;
	work->obj_id = FieldOBJ_OBJIDGet( work->head.fldobj );
	work->zone_id = FieldOBJ_ZoneIDGet( work->head.fldobj );
	work->move.y = P_BALLON_FLDOBJ_Y_MOVE_START;
	{
		NNSG3dResTex* tex_res_dst;
		int ballon_type = EOA_AddParamGet(eoa);
#ifdef PM_DEBUG
		if (debug_ballon_type){
			ballon_type = debug_ballon_type-1;
		}
#endif
		//アニメテーブルデータをロードして、アニメテーブルを保持する
		work->TexAnime.TexData = FE_ArcDataLoadAlloc( work->head.fes, BallonArcData[ballon_type].TexArc, ALLOC_LO );
		work->TexAnime.AnmData = FE_ArcDataLoadAlloc( work->head.fes, BallonArcData[ballon_type].ItpArc, ALLOC_LO );
		TEXANM_UnPackLoadFile( work->TexAnime.AnmData, &work->TexAnime.AnmTbl );
		work->TexAnime.ResTex = NNS_G3dGetTex( (NNSG3dResFileHeader*)work->TexAnime.TexData  );	// テクスチャリソース取得


		//アニメ内部データの初期化
		work->TexAnime.Frame = 0;
		work->TexAnime.TblIdx = 0;

		//転送先テクスチャリソースの取得
		tex_res_dst = FE_GetTexRes(work->head.fes, FE_RESID_TEX_P_BALLON);
		//テクスチャサイズ取得
		work->TexAnime.TexSize = GetTexByteSize(tex_res_dst, 0);
		//転送先アドレス取得
		work->TexAnime.TexDstAdr = GetTexStartVRAMAdr(tex_res_dst, 0);

		//初期テクスチャデータを転送
		AddVramTransferManager(
						NNS_GFD_DST_3D_TEX_VRAM,		//転送セット
						(u32)work->TexAnime.TexDstAdr,
						GetTexStartAdr(work->TexAnime.ResTex, 0),
						work->TexAnime.TexSize);
		AddVramTransferManager(
						NNS_GFD_DST_3D_TEX_PLTT,		//転送セット
						NNS_GfdGetPlttKeyAddr( tex_res_dst->plttInfo.vramKey ),
						GetPlttStartAdr(work->TexAnime.ResTex, 0),
						POKE_BALLON_PLTT_SIZE);
	}
//	GraphicInit( work->head.ballon );	//グラフィック初期化

	EOA_MatrixGet( eoa, &vec );
	work->act = BlActAdd( work->head.fes, &vec );

	//はじめ非表示
	BLACT_ObjDrawFlagSet(work->act, 0);

	if( /*EOA_AddParamGet(eoa) == TRUE*/1 ){
		Snd_SePlay( SE_MARK_GYOE );
	}

	return( TRUE );
}

//--------------------------------------------------------------
/**
 * EOA 　削除
 * @param	eoa		EOA_PTR
 * @param	wk		eoa work *
 * @retval	nothing
 */
//--------------------------------------------------------------
static void EoaP_Ballon_Delete( EOA_PTR eoa, void *wk )
{
	P_BALLON_WORK *work;

	work = wk;

	BLACT_Delete( work->act );			//アクター削除

	//テクスチャ転送アニメデータ解放
	sys_FreeMemoryEz(work->TexAnime.AnmData);
	sys_FreeMemoryEz(work->TexAnime.TexData);

//	GraphicDelete( work->head.ballon );	//グラフィック削除
}

//--------------------------------------------------------------
/**
 * EOA 　動作
 * @param	eoa		EOA_PTR
 * @param	wk		eoa work *
 * @retval	nothing
 */
//--------------------------------------------------------------
static void EoaP_Ballon_Move( EOA_PTR eoa, void *wk )
{
	P_BALLON_WORK *work;
	FIELD_OBJ_PTR fldobj;
	VecFx32 vec;

	work = wk;
	fldobj = work->head.fldobj;

	GF_ASSERT_MSG( FieldOBJ_CheckSameID(fldobj,work->obj_id,work->zone_id) != FALSE,
		"動作中に対象のフィールドOBJが削除されました\n" );

	{
		VecFx32 vec_pos,vec_offs,vec_out,vec_attr;
		FieldOBJ_VecPosGet( fldobj, &vec_pos );
		FieldOBJ_VecDrawOffsGet( fldobj, &vec_offs );
		FieldOBJ_VecDrawOffsOutSideGet( fldobj, &vec_out );
		FieldOBJ_VecAttrOffsGet( fldobj, &vec_attr );
		vec.x = vec_pos.x + vec_offs.x + vec_out.x + vec_attr.x;
		vec.y = vec_pos.y + vec_out.y + vec_attr.y;
		vec.z = vec_pos.z + vec_offs.z + vec_out.z + vec_attr.z;
	}
	vec.y += P_BALLON_FLDOBJ_Y_OFFSET;
	vec.z += P_BALLON_FLDOBJ_Z_OFFSET;

	switch( work->seq_no ){
	case 0:
		//表示
		BLACT_ObjDrawFlagSet(work->act, 1);

		work->offset.y += work->move.y;

		if( work->offset.y > 0 ){
			work->move.y -= FX32_ONE * 2;
		}else{
			work->offset.y = 0;
			work->move.y = 0;
			work->seq_no++;
		}

		break;
	case 1:			//転送アニメ
		if ( VRAMTransMain(&work->TexAnime) ){
			work->seq_no++;
		}
		break;
	case 2:
		work->frame++;

		if( work->frame >= P_BALLON_END_FRAME ){
			work->seq_no++;
			work->frame = 0;
			work->end_sw = TRUE;
		}

		break;
	case 3:
		//追加許可
		work->head.ballon->AddFlg = FALSE;
		//削除
		FE_EoaDelete( eoa );

		return;
	}

	EOA_MatrixSet( eoa, &vec );
}

//--------------------------------------------------------------
/**
 * EOA 　描画
 * @param	eoa		EOA_PTR
 * @param	wk		eoa work *
 * @retval	nothing
 */
//--------------------------------------------------------------
static void EoaP_Ballon_Draw( EOA_PTR eoa, void *wk )
{
	VecFx32 vec;
	P_BALLON_WORK *work;

	work = wk;

	if( work->vanish_sw == TRUE ){
		return;
	}

	EOA_MatrixGet( eoa, &vec );

	vec.x += work->offset.x;
	vec.y += work->offset.y;
	vec.z += work->offset.z;

	BLACT_MatrixSet( work->act, &vec );
}

//--------------------------------------------------------------
/**
 *	転送メイン
 * @param	inAnm	吹き出しアニメ
 * @retval	BOOL	1ループ転送終了
 */
//--------------------------------------------------------------
static BOOL VRAMTransMain(BALLON_ANIME *inAnm)
{
	//フレーム取得
	if (++inAnm->Frame >= inAnm->AnmTbl.cp_frame[inAnm->TblIdx]){
		inAnm->TblIdx++;
		inAnm->Frame = 0;
		if (inAnm->TblIdx >= inAnm->AnmTbl.tbl_num){
			return TRUE;
		}

		AddVramTransferManager(
					NNS_GFD_DST_3D_TEX_VRAM,		//転送セット
					(u32)inAnm->TexDstAdr,
					GetTexStartAdr(inAnm->ResTex, inAnm->AnmTbl.cp_tex_idx[inAnm->TblIdx]),
					inAnm->TexSize);
	}
	return FALSE;
}

//==============================================================================
//	data
//==============================================================================
//--------------------------------------------------------------
///	EOA_H
//--------------------------------------------------------------
static const EOA_H_NPP DATA_EoaH_PokeBallon =
{
	P_BALLON_WORK_SIZE,
	EoaP_Ballon_Init,
	EoaP_Ballon_Delete,
	EoaP_Ballon_Move,
	EoaP_Ballon_Draw,
};

//--------------------------------------------------------------
///	ギョエーアニメ
//--------------------------------------------------------------
static const BLACT_ANIME_TBL DATA_BlActAnmTbl_PokeBallon[] =
{
	{ 0, 1, BLACT_ANIM_LOOP },
	{ 0, 0, BLACT_ANIM_CMD_MAX },
};
